<?php
/**
 * 需求审核状态基类；
 * @author shipanpan
 */
abstract class Application_Model_StoryStatus extends Model_Base {
	protected $_storyId;
	//待审核的需求
	protected $_story;
	protected $_storyModel;

	const PRIMARY_TEAM_LEADER_ROLE = 1;
	const ADVANCED_TEAM_LEADER_ROLE = 2;
	const TEAM_MANAGER_ROLE = 3;
	const MANAGER_ROLE = 4;

	public function __construct(int $storyId) {
		$this->db = $this->db();
		$this->writeDb = $this->db('write_db');

		$this->_storyId = $storyId;
		$this->_storyModel = new Application_Model_Story();
	}

	/**
	 * 获取需求能被当前状态类处理的初始状态
	 * @return [type] [description]
	 */
	abstract public function getHandleInitStatus();

	/**
	 * 获取需求被当前状态类处理为驳回后的状态
	 * @return [type] [description]
	 */
	abstract public function getHandleRejectStatus();

	/**
	 * 获取需求被当前状态类处理为审核通过后的状态
	 * @return [type] [description]
	 */
	public function getHandleAgreeStatus() {
		return Application_Model_Story::EXAMINE_PASS;
	}

	/**
	 * 获取当前状态类的下一个状态类，例如 待小组长审核状态类 的下一个状态就是 待大组长审核 ，
	 * 那么下一个状态类就是 大组长审核状态类
	 * @return [type] [description]
	 */
	abstract public function getSuperior();

	/**
	 * 获取当前状态类的审核角色类型；对应c_warehouse_ex表的auditor字段(1-小组长；2-大组长；3-主管；4-经理）；
	 * @return [type] [description]
	 */
	abstract public function getCheckerRoleType();

	abstract public function getCheckerRole();

	/**
	 * 需求审核
	 * @param  [type] $isPass 是否是审核通过
	 * @return [type]         [description]
	 */
	public function check(bool $isPass) {
		$story = $this->_getStory();
		$storyStatus = $story['examine_status'];
		if ($storyStatus != $this->getHandleInitStatus()) {
			$storyStatusName = Application_Model_Story::getExamineStatusName($storyStatus);
			throw new Exception('需求当前状态为:' . $storyStatusName . ',不能进行审核操作！');
		}
		if ($story['create_date'] != date("Y-m-d")) {
			throw new Exception('只能审核当日需求！');
		}
		if ($story['delete_flag']) {
			throw new Exception('需求已经被标记为删除，不能进行审核操作！');
		}

		$afterCheckStatus = $this->getHandleAgreeStatus();
		if ($isPass) {
			if ($this->_needSuperiorCheck()) {
				$afterCheckStatus = $this->getSuperior()->getHandleInitStatus();
			}
		} else {
			$afterCheckStatus = $this->getHandleRejectStatus();
		}

		$this->writeDb->beginTransaction();
		try {
			$statusUpdateResult = $this->_storyModel->statusUpdate($this->_storyId, $afterCheckStatus, false);
			$this->_checkLog($this->_storyId, $isPass);
			if ($statusUpdateResult === false) {
				$this->writeDb->rollBack();
			}
			$this->writeDb->commit();
			return true;
		} catch (Exception $e) {
			$this->writeDb->rollBack();
			throw $e;
		}

		if ($statusUpdateResult === false) {
			throw new Exception($this->_storyModel->getErrorMsg());
		}
	}

	/**
	 * 记录需求审核日志
	 * @param  [type] $storyId 被审核的需求id
	 * @param  [type] $isPass  是否审核通过
	 * @return [type]          [description]
	 */
	protected function _checkLog($storyId, bool $isPass) {
		$data['handle_user'] = is_null(Model_User::currentLoginUser()->user_name) ? 'system' : Model_User::currentLoginUser()->user_name;
		$data['story_id'] = $storyId;
		$data['handle_role'] = $this->getCheckerRole();
		$data['handle_type'] = $isPass ? 1 : 2;

		return $this->writeDb->insert('b_story_examine_log', $data);
	}

	/**
	 * 需求是否需要当前状态类的审核
	 * @return [type] [description]
	 */
	public function needCheck() {
		if ($this->_warehouseRuleCheck()) {
			return true;
		}
		return false;
	}

	/**
	 * 需求对应仓库的审核规则检查
	 * @return [type] [description]
	 */
	protected function _warehouseRuleCheck() {
		$story = $this->_getStory();
		$warehouse = $story['warehouse_code'];
		$platformWarehouse = $story['platform_warehouse'];
		//当需求属于平台仓时，使用平台仓的需求审核规则
		if ($platformWarehouse) {
			$isPlatformWarehouse = true;
			$warehouse = $platformWarehouse;
		}

		$warehouseInfo = $this->db->fetchRow('select * from c_warehouse where warehouse_code=' . $this->db->quote($warehouse));
		if (!$warehouseInfo) {
			$errorMsg = '未找到需求的所属' . (isset($isPlatformWarehouse) ? "平台仓！" : '仓库！');
			throw new Exception($errorMsg);
		}
		//如果仓库设置为不需要审核需求，那么直接审核通过
		if ($warehouseInfo['demand_examine'] == 1) {
			return false;
		}

		//当仓库设置需求需要审核但有没有设置任何详细的审核规则时，默认需要审核
		$warehouseCheckRule = $this->db->fetchAll("select * from c_warehouse_ex where warehouse_code=" . $this->db->quote($warehouse));
		if (!$warehouseCheckRule) {
			return true;
		}

		$allRoleCheckRule = array_column($warehouseCheckRule, null, 'auditor');
		$roleTypeId = $this->getCheckerRoleType();
		$roleCheckRule = $allRoleCheckRule[$roleTypeId] ?? false;
		if (!$roleCheckRule) {
			return false;
		}

		if (($this->_getStoryAmountMoney() >= $roleCheckRule['quota']) || ($this->_getStoryBackupQuantity() >= $roleCheckRule['maxnum'])) {
			return true;
		}
		return false;
	}

	/**
	 * 需求是否还需要下一级审核
	 * @return [type] [description]
	 */
	protected function _needSuperiorCheck() {
		$story = $this->_getStory();
		$superior = $this->getSuperior();
		if ($superior) {
			return $superior->needCheck();
		}
		return false;
	}

	/**
	 * 获取被审核需求信息
	 * @return [type] [description]
	 */
	protected function _getStory() {
		if (is_array($this->_story)) {
			return $this->_story;
		}

		$story = $this->writeDb->fetchRow("select * from b_story where id=" . $this->_storyId);
		if (!$story) {
			throw new Exception("未找到需求id为:" . $this->_storyId . "的需求！");
		}
		$this->_story = $story;

		return $this->_story;
	}

	/**
	 * 获取需求备货数量
	 * @return [type] [description]
	 */
	protected function _getStoryBackupQuantity() {
		$story = $this->_getStory();
		return $story['a_story_quantity'] + $story['b_story_quantity'] + $story['c_story_quantity'];
	}

	/**
	 * 获取需求备货总金额
	 */
	protected function _getStoryAmountMoney() {
		return $this->_getStoryBackupQuantity() * $this->_getStoryGoodsPrice();
	}

	/**
	 * 获取产品价格
	 * @return [type] [description]
	 */
	protected function _getStoryGoodsPrice() {
		$story = $this->_getStory();
		return $this->db->fetchOne("select purchase_price from p_product_purchase where goods_sn=" . $this->db->quote($story['goods_sn']));
	}
}